#[macro_use] extern crate log;
use std::collections::BTreeSet;
+use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::{Path,PathBuf};
use cargo::core::shell::Verbosity;
use cargo::execute_main_without_stdin;
-use cargo::util::{self, CliResult, lev_distance, Config, human};
+use cargo::util::{self, CliResult, lev_distance, Config, human, CargoResult};
use cargo::util::CliError;
use cargo::util::process_builder::process;
return Ok(None)
}
- let args = match &flags.arg_command[..] {
+ let mut args = match &flags.arg_command[..] {
// For the commands `cargo` and `cargo help`, re-execute ourselves as
// `cargo -h` so we can go through the normal process of printing the
// help message.
// For all other invocations, we're of the form `cargo foo args...`. We
// use the exact environment arguments to preserve tokens like `--` for
// example.
- _ => env::args().collect(),
+ _ => {
+ let mut default_alias = HashMap::new();
+ default_alias.insert("b", "build".to_string());
+ default_alias.insert("t", "test".to_string());
+ default_alias.insert("r", "run".to_string());
+ let mut args: Vec<String> = env::args().collect();
+ if let Some(new_command) = default_alias.get(&args[1][..]){
+ args[1] = new_command.clone();
+ }
+ args
+ }
};
+ let alias_list = try!(aliased_command(&config, &args[1]));
+ if let Some(alias_command) = alias_list {
+ // Replace old command with new command and flags
+ let chain = args.iter().take(1)
+ .chain(alias_command.iter())
+ .chain(args.iter().skip(2))
+ .map(|s| s.to_string())
+ .collect();
+ args = chain;
+ }
+
macro_rules! cmd{
($name:ident) => (if args[1] == stringify!($name).replace("_", "-") {
config.shell().set_verbosity(Verbosity::Verbose);
Ok(None)
}
+fn aliased_command(config: &Config, command: &String) -> CargoResult<Option<Vec<String>>> {
+ let alias_name = format!("alias.{}", command);
+ let mut result = Ok(None);
+ match config.get_string(&alias_name) {
+ Ok(value) => {
+ if let Some(record) = value {
+ let alias_commands = record.val.split_whitespace()
+ .map(|s| s.to_string())
+ .collect();
+ result = Ok(Some(alias_commands));
+ }
+ },
+ Err(_) => {
+ let value = try!(config.get_list(&alias_name));
+ if let Some(record) = value {
+ let alias_commands: Vec<String> = record.val.iter()
+ .map(|s| s.0.to_string()).collect();
+ result = Ok(Some(alias_commands));
+ }
+ }
+ }
+ result
+}
+
fn find_closest(config: &Config, cmd: &str) -> Option<String> {
let cmds = list_commands(config);
// Only consider candidates with a lev_distance of 3 or less so we don't
# Network configuration
[net]
retry = 2 # number of times a network call will automatically retried
+
+# Alias cargo commands. The first 3 aliases are built in. If your
+command requires grouped whitespace use the list format.
+[alias]
+b = "build"
+t = "test"
+r = "run"
+rr = "run --release"
+space_example = ["run", "--release", "--", "\"command list\""]
```
# Environment Variables
--- /dev/null
+extern crate cargotest;
+extern crate hamcrest;
+use cargotest::support::{project, execs, basic_bin_manifest};
+use hamcrest::{assert_that};
+
+#[test]
+fn alias_incorrect_config_type() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ b-cargo-test = 5
+ "#);;
+
+ assert_that(p.cargo_process("b-cargo-test").arg("-v"),
+ execs().with_status(101).
+ with_stderr_contains("[ERROR] invalid configuration \
+for key `alias.b-cargo-test`
+expected a list, but found a integer in [..]"));
+}
+
+
+#[test]
+fn alias_default_config_overrides_config() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ b = "not_build"
+ "#);;
+
+ assert_that(p.cargo_process("b").arg("-v"),
+ execs().with_status(0).
+ with_stderr_contains("[COMPILING] foo v0.5.0 [..]"));
+}
+
+#[test]
+fn alias_config() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ b-cargo-test = "build"
+ "#);;
+
+ assert_that(p.cargo_process("b-cargo-test").arg("-v"),
+ execs().with_status(0).
+ with_stderr_contains("[COMPILING] foo v0.5.0 [..]
+[RUNNING] `rustc [..] --crate-name foo --crate-type \
+bin -g --out-dir [..] --emit=dep-info,link -L dependency=[..]\
+-L dependency=[..]"));
+}
+
+#[test]
+fn alias_list_test() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ b-cargo-test = ["build", "--release"]
+ "#);;
+
+ assert_that(p.cargo_process("b-cargo-test").arg("-v"),
+ execs().with_status(0).
+ with_stderr_contains("[COMPILING] foo v0.5.0 [..]").
+ with_stderr_contains("[RUNNING] `rustc [..] --crate-name foo \
+ --crate-type bin -C opt-level=3 --out-dir [..]\
+ --emit=dep-info,link -L dependency=[..]")
+ );
+}
+
+#[test]
+fn alias_with_flags_config() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ b-cargo-test = "build --release"
+ "#);;
+
+ assert_that(p.cargo_process("b-cargo-test").arg("-v"),
+ execs().with_status(0).
+ with_stderr_contains("[COMPILING] foo v0.5.0 [..]").
+ with_stderr_contains("[RUNNING] `rustc [..] --crate-name foo \
+ --crate-type bin -C opt-level=3 --out-dir [..]\
+ --emit=dep-info,link -L dependency=[..]")
+ );
+}